﻿//----------------------------------------------------------------
// Desc: 
// Edit: ShowLong, http://blog.csdn.net/showlong
//
// Date Created: 2009-10-15
//
// Update Date :            
//
// Copyright (c) Fuel4D (http://www.fuel4d.com), All rights reserved.
//
//----------------------------------------------------------------
#pragma once


//----------------------------------------------------------------
// 下面两个宏配套使用，上者用于自动创建FU_TR_ITEM成员查询递归函数，下者用于生成FUI_Tree查询接口
//----------------------------------------------------------------
#define FUI_Tree_Item_Find_Auto_Func(name, type, param, exp)\
    FU_TR_ITEM* FindBy##name(type param)\
    {\
        if (exp)\
            return this;\
        for (int i = 0; i < Count(); ++i)\
        {\
            FU_TR_ITEM* ret = Get(i)->FindBy##name(param);\
            if (ret)\
                return ret;\
        }\
        return 0;\
    };
#define FUI_Tree_Contorl_Find_Auto_Func(name, type, param1, param2)\
    FU_TR_ITEM* FindBy##name(type param1, FU_TR_ITEM* param2 = 0)\
    {\
        FU_TR_ITEM* pnode = param2 ? param2 : pTreeRoot;\
        return pnode->FindBy##name(param1);\
    }


//----------------------------------------------------------------
// 树项
//----------------------------------------------------------------
class FUI_Tree;
class FAPI FU_TR_ITEM
{
    FUI_DECLARE_STRUCT(FU_TR_ITEM);

    friend class FUI_Tree;

    typedef FUI_Vector< FU_TR_ITEM* > FV_UI_PTR_ITEM;

protected:
    FU_TR_ITEM* pFather;
    FV_UI_PTR_ITEM vChild;
    bool bOpen;             // 是否是打开的
    int nHeight;            // 此项的高度
    bool bSelect;           // 当前是否是选中项
    bool bSuspend;          // 当前是否是悬停项

public:
    WCHAR szText[128];      // 该项显示的内容
    DWORD dwColor;          // 如果此值为0，则使用UI编辑器设置的字体颜色
    bool bCheck;            // 复选框状态
    int nID;                // ID号 (控件不用，由使用者控制)
    DWORD_PTR dwDataPtr;    // 数据 (控件不用，由使用者控制)

protected:
    FU_TR_ITEM(fuWidgetTree* data, const WCHAR* name);
    FU_TR_ITEM(fuWidgetTree* data, const ACHAR* name);
    int GetHeight();
    // 返回表示是否结束循环
    bool Draw(FUI_Tree* pTree, fuPoint& pt, int w, fuRect* dst, bool text, int& idx);
    void Open(bool open);
    void Check(bool check);
    static void GetRect(FUI_Tree* pTree, FU_TR_ITEM* pData, fuPoint& pt, int w, fuRect* dst, fuRect& add_sub, fuRect& text, fuRect& check);
    FU_TR_ITEM* GetItem(FUI_Tree* pTree, fuPoint& pt, int w, funit mx, funit my, fuRect* dst, bool autocheck, bool autoopen);

    FUI_Tree_Item_Find_Auto_Func(Text, const WCHAR*, param, wcscmp(param, szText) == 0)
    FUI_Tree_Item_Find_Auto_Func(Text, const ACHAR*, param, strcmp(param, FUI_StringA(szText).c_str()) == 0)
    FUI_Tree_Item_Find_Auto_Func(ID, int, param, param == nID)
    FUI_Tree_Item_Find_Auto_Func(DataPtr, DWORD_PTR, param, param == dwDataPtr)

public:
    void Release();
    FINLINE int Count(){ return (int)vChild.size(); }
    FINLINE bool IsOpen(){ return bOpen; }
    FINLINE bool IsSelect(){ return bSelect; }
    FINLINE bool IsSuspend(){ return bSuspend; }
    FINLINE FU_TR_ITEM* Get(int index){ assert(index >= 0 && index < Count()); return vChild[index]; }
    FINLINE void Add(FU_TR_ITEM* node){ node->pFather = this; vChild.push_back(node); }
    FINLINE bool IsLeaf(){ return vChild.empty(); }
    FINLINE FU_TR_ITEM* Father(){ return pFather; }
    FINLINE int GetMyHeight(){ return nHeight; }
};


//----------------------------------------------------------------
// 自定义绘制函数，返回该会绘制了多高
// .non_text 绘制哪一层，图片层/文本层
// .add_sub  加减号的绘制区域（绘制图片层时有效）
// .text     该节点的文本绘制区域
// .check    该节点的复选框绘制区域（有复选框时）
//----------------------------------------------------------------
class FUI_Tree;
typedef void (*FUI_Tree_Render)(FUI_Tree* pdata, FU_TR_ITEM* pData, bool non_text, fuRect* add_sub, fuRect* text, fuRect* check);


//----------------------------------------------------------------
//
//----------------------------------------------------------------
class FAPI FUI_Tree : public FUI_Object
{
    FUI_DECLARE_CLASS(FUI_Tree)

    friend class FU_TR_ITEM;

public:
    FUI_Tree(EF_UI_WIDGET_TYPE t = eUWT_Tree);
    virtual void Release();
    virtual void Render(EF_UI_RENDER_LAYER layer);
    virtual void UpdateRect();
    virtual void OnFrameHide(bool visable);
    virtual bool IsChild(FUI_Object* pChild);
    virtual bool HasClip(){ return true; }
    virtual void SetHeight(funit h);
    virtual bool OnMouseMove(funit nX, funit nY);
    virtual bool OnMouseWheel(bool bUp, funit nX, funit nY);
    virtual bool OnLButtonDown(funit nX, funit nY);
    virtual bool OnLButtonUp(funit nX, funit nY);
    virtual bool OnLButtonDBClick(funit nX, funit nY);

    // 添加节点
    // .father 如果为0表示添加根节点
    // .height 大于0表示设置该行条目的高度，否则使用编辑器中设置的高度
    FU_TR_ITEM* AddItem(const WCHAR* name, FU_TR_ITEM* father = 0, int height = 0);
    FU_TR_ITEM* AddItem(const ACHAR* name, FU_TR_ITEM* father = 0, int height = 0);
    // 删除节点
    void DelItem(FU_TR_ITEM* item);
    // 打开节点
    void OpenTree(FU_TR_ITEM* item, bool open);
    // 单击节点
    void CheckTree(FU_TR_ITEM* item, bool check);
    // 设置项高
    void SetItemHeight(FU_TR_ITEM* dst, int height);
    // 获取相关节点
    FINLINE FU_TR_ITEM* GetRoot(){ return pTreeRoot; }
    FINLINE FU_TR_ITEM* GetSelect(){ return pSelectItem; }
    FINLINE FU_TR_ITEM* GetSuspend(){ return pSuspendItem; }
    // 选中某个节点
    FU_TR_ITEM* SetSelectByText(const WCHAR* text);
    FU_TR_ITEM* SetSelectByText(const ACHAR* text);
    FU_TR_ITEM* SetSelectByItem(FU_TR_ITEM* item);
    // 树是否是空的
    FINLINE bool IsNullTree(){ return pTreeRoot->Count() == 0; }
    // 清空树
    void Clear();
    // 设置渲染函数
    FINLINE void SetRenderFunc(FUI_Tree_Render render){ pTreeRender = render; }
    // 树项查询相关
    FU_TR_ITEM* GetNextSiblingItem(FU_TR_ITEM* hItem);
    FU_TR_ITEM* GetPrevSiblingItem(FU_TR_ITEM* hItem);
    FU_TR_ITEM* GetFatherItem(FU_TR_ITEM* hItem);
    // 设置控件数据
    FINLINE void SetHasCheck(bool bCheck){ pTreeData->SetHasCheck(bCheck); }
    FINLINE bool IsHasCheck(){ return pTreeData->IsHasCheck(); }
    FINLINE void SetCheckAtLeft(bool left){ pTreeData->SetCheckAtLeft(left); }
    // 获取部分控件数据
    FINLINE FUI_ScrollBar& GetScroll(){ return uScrollBar; }

    FUI_Tree_Contorl_Find_Auto_Func(Text, const WCHAR*, param1, param2)
    FUI_Tree_Contorl_Find_Auto_Func(Text, const ACHAR*, param1, param2)
    FUI_Tree_Contorl_Find_Auto_Func(ID, DWORD, param1, param2)
    FUI_Tree_Contorl_Find_Auto_Func(DataPtr, DWORD_PTR, param1, param2)

protected:
    virtual void InitUIData(FUI_Object* father, fuWidgetBase* pData, FUI_Layout* layout);
    virtual void Update();

    void RenderTree(bool text);
    void CancelSelect();
    void CancelSuspend();
    void SetSelect(FU_TR_ITEM* pdata);

protected:
    fuWidgetTree* pTreeData;        // 控件数据地址
    FUI_ScrollBar uScrollBar;
    FU_TR_ITEM* pTreeRoot;          // 树根(创建控件的时候自动NEW出来)
    FU_TR_ITEM* pSelectItem;        // 当前选中的项
    FU_TR_ITEM* pSuspendItem;       // 当前鼠标悬停的项
    FUI_Tree_Render pTreeRender;    // 自定义绘制函数
};
